package com.enzo.prms.common.exception.util;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;

public class ClassUtil {
	
	public static Set<Class<?>> getClassesFromPackage(String packageName){
		Set<Class<?>> classes=new LinkedHashSet<Class<?>>();
		String packageDirName=packageName.replace('.', '/');
		
		Enumeration<URL> dirs;
		
		try {
			dirs=Thread.currentThread().getContextClassLoader().getResources(packageDirName);
			while (dirs.hasMoreElements()) {
				URL url = (URL) dirs.nextElement();
				String protocol=url.getProtocol();
				if("file".equals(protocol)){
					String filePath=URLDecoder.decode(url.getFile(), "utf-8");
					findAndAddClassesInPackageByFile(packageName, filePath, classes);
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		return classes;
	}
	
	public static void findAndAddClassesInPackageByFile(String packageName,
			            String packagePath,Set<Class<?>> classes) {
		// 获取此包的目录 建立一个File
		File dir = new File(packagePath);
		// 如果不存在或者 也不是目录就直接返回
		if (!dir.exists() || !dir.isDirectory()) {
			// log.warn("用户定义包名 " + packageName + " 下没有任何文件");
			return;
		}
		// 如果存在 就获取包下的所有文件 包括目录
		File[] dirfiles = dir.listFiles(new FileFilter() {
			// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
			public boolean accept(File file) {
				return file.getName().endsWith(".class");
			}
		});
		
		// 循环所有文件
		for (File file : dirfiles) {
			// 如果是java类文件 去掉后面的.class 只留下类名
			String className = file.getName().substring(0,file.getName().length() - 6);
			try {
				// 添加到集合中去
				// classes.add(Class.forName(packageName + '.' + className));
				// 经过回复同学的提醒，这里用forName有一些不好，会触发static方法，没有使用classLoader的load干净
				classes.add(Thread.currentThread().getContextClassLoader()
						.loadClass(packageName + '.' + className));
			} catch (ClassNotFoundException e) {
				// log.error("添加用户自定义视图类错误 找不到此类的.class文件");
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		Set<Class<?>> classes=getClassesFromPackage("com.enzo.prms.common.exception.base");
		System.out.println(classes);
	}
}
